﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml.Serialization;
using SoftwareConsulting;
using SoftwareConsulting.BI11.StringResources;
using SoftwareConsulting.BI11.Studio.Core.Project;
using SoftwareConsulting.BI11.Studio.Core.Project.LogicalInferenceMechanism;
using SoftwareConsulting.BI11.Studio.Core.Project.Metadata;
using SoftwareConsulting.BI11.Studio.Core.Project.SituationsHierarchy;
using SoftwareConsulting.Interfaces.BasicEntities;
using SoftwareConsulting.BI11.Studio.InternalServices;

namespace SoftwareConsulting.BI11.Studio.UI.LogicalInferenceMechanism
{
	public partial class LogicalInferenceStartDialog : Form
	{
		private ProjectDescriptor _project; //для связи с проектом                
        private int[] state;
        private bool created;

        /// <summary>
        /// Обрабатывает изменения в гриде строк таблицы
        /// </summary>
        /// <param name="rowIndex"></param>
        private void ProcessRowsGridChange(int rowIndex)
        {
            if (created && grdRows.CurrentCell != null)
            {
                state[grdCharacteristics.CurrentCell.RowIndex] = rowIndex;
            }
        }

        /// <summary>
        /// Обрабатывает изменения в гриде характеристик
        /// </summary>
        /// <param name="rowIndex"></param>
        private void ProcessCharacteristicsGridChange(int rowIndex)
        {
            Characteristic locCharacteristic = null;            
            string cName;

            if (created)
            {
                created = false;
                cName = grdCharacteristics.Rows[rowIndex].Cells[0].Value.ToString();
                INamedHierarchy<Characteristic> chs = _project.GetCharacteristicsByName(cName.ToString());                
                foreach (Characteristic ch in chs)
                {
                    locCharacteristic = ch;
                    break;
                }                

                if (locCharacteristic.DomainType == DomainType.Table)
                {
                    DataGridViewComboBoxCell cbox = (grdCharacteristics.Rows[rowIndex].Cells[1] as DataGridViewComboBoxCell);
                    IUserTable tab = _project.Repository.GetTableByLabel(cbox.Value.ToString());
                    tab.ConnectDataGrid(grdRows);
                    grdRows.Refresh();
                    if (grdRows.Rows.Count > 0)
                    {
                        grdRows.CurrentCell = grdRows[1, state[rowIndex]];
                    }
                }
                else
                {
                    grdRows.DataSource = null;
                    grdRows.Refresh();
                }
                created = true;
            }
        }

        /// <summary>
        /// Сохраняет настройки диалога
        /// </summary>
        private void SaveSettings()
        {
            UpdateLIM();
            _project.SerializeLIM();            
        }

        /// <summary>
        /// Инициализация диалога
        /// </summary>
        private void Initialize()
        {
            created = false;
            Characteristic locCharacteristic = null;
            Domain locDomain;
            string cName;
            LIMItemsCollection itemsCollection = _project.LIMItemsCollection;
            state = new int[itemsCollection.ItemsCount];
            foreach (LIMItem li in itemsCollection)
            {
                cName = li.Name;
                INamedHierarchy<Characteristic> chs = _project.GetCharacteristicsByName(cName.ToString());
                foreach (Characteristic ch in chs)
                {
                    locCharacteristic = ch;
                    break;
                }
                locDomain = _project.GetDomainById(locCharacteristic.DomainId);
                grdCharacteristics.Rows.Add();
                // название характеристики
                grdCharacteristics.Rows[grdCharacteristics.Rows.Count - 1].Cells[0].Value = cName;
                // цикл по всем элементам домена
                DataGridViewComboBoxCell cbox = (grdCharacteristics.Rows[grdCharacteristics.Rows.Count - 1].Cells[1] as DataGridViewComboBoxCell);
                for (int j = 0; j < locDomain.ItemsCount; j++)
                {
                    DomainItem di = locDomain.GetItemByPosition(j);
                    object obj = di.Value;
                    if (obj != null)
                        cbox.Items.Add(obj.ToString());
                    else
                        cbox.Items.Add(Resources.RS_NULL_OBJECT_LIMSTART_DIALOG);
                }
                // устанавливаем значение
                LIMItem locLIMItem = _project.GetLIMitemByName(cName);
                if (locLIMItem.Value != null)
                {
                    INamedHierarchy<Characteristic> chs2 = _project.GetCharacteristicsByName(locLIMItem.Name);                    
                    Characteristic ch = null;
                    foreach (Characteristic ch2 in chs2)
                    {
                        ch = ch2;
                        break;
                    }
                    //DataGridViewButtonCell but = grdCharacteristics.Rows[grdCharacteristics.Rows.Count - 1].Cells[2] as DataGridViewButtonCell;
                    if (ch.DomainType != DomainType.Table)
                    {
                        cbox.Value = locLIMItem.Value.ToString();                        
                    }
                    else
                    {
                        string locRow = locLIMItem.Value as string;
                        string TableLabel = locRow.Split('|')[0];
                        int rowIndex = Convert.ToInt32(locRow.Split('|')[1],CultureInfo.CurrentCulture);
                        cbox.Value = TableLabel;
                        if (_project.Repository.GetTableByLabel(TableLabel).GetRowsCount() >= rowIndex)
                            state[grdCharacteristics.RowCount - 1] = rowIndex;
                    }                    
                }
                else
                    cbox.Value = Resources.RS_NULL_OBJECT_LIMSTART_DIALOG;
            }
            created = true;
            UpdateCurrentCell();
            //заполнение комбика миров
            ComboBox.ObjectCollection items = WorldsBox.Items;
            IFactsDimension wdim = _project.Repository.WorldsDimension;
            INamedHierarchy<INamed> wdimitems = wdim.Items;
            foreach(INamed wdimitem in wdimitems)
            {                
                items.Add(wdimitem.Name);
            }
            int lwkey = _project.LastWorldKey;
            WorldsBox.SelectedItem = _project.Repository.GetWorldNameByKey(lwkey);
        }		

		private void UpdateCurrentCell()
		{
            Characteristic locCharacteristic = null;			
			string cName;

			if (created && grdCharacteristics.CurrentCell != null)
			{
				grdCharacteristics.EndEdit();
				cName = grdCharacteristics.Rows[grdCharacteristics.CurrentCell.RowIndex].Cells[0].Value.ToString();
                INamedHierarchy<Characteristic> chs = _project.GetCharacteristicsByName(cName.ToString());
                foreach (Characteristic ch in chs)
                {
                    locCharacteristic = ch;
                    break;
                }                
                DataGridViewComboBoxCell cbox = (grdCharacteristics.Rows[grdCharacteristics.CurrentCell.RowIndex].Cells[1] as DataGridViewComboBoxCell);
                string chval = cbox.Value.ToString();
                switch (locCharacteristic.DomainType)
                {
                    case DomainType.Table:
                        IUserTable tab = _project.Repository.GetTableByLabel(chval);
                        tab.ConnectDataGrid(grdRows);
                        grdRows.Refresh();
                        if (grdRows.Rows.Count > 0)
                            grdRows.CurrentCell = grdRows[0, state[grdCharacteristics.CurrentCell.RowIndex]];
                        break;                    
                }
			}
		}

        /// <summary>
        /// Обновляет МЛВ в соответствии с выбранными значениями
        /// </summary>
        private void UpdateLIM()
        {
            Characteristic locCharacteristic = null;

            // цикл по всем элментам грида
            for (int i = 0; i < grdCharacteristics.Rows.Count; i++)
            {
                DataGridViewComboBoxCell cbox = (grdCharacteristics.Rows[i].Cells[1] as DataGridViewComboBoxCell);
                string cName = grdCharacteristics.Rows[i].Cells[0].Value.ToString();
                INamedHierarchy<Characteristic> chs = _project.GetCharacteristicsByName(cName.ToString());
                foreach (Characteristic ch in chs)
                {
                    locCharacteristic = ch;
                    break;
                }
                // если значение комбокса не null
                if (!GeneralMethods.IsNullString(cbox.Value))
                {
                    Domain locDomain = _project.GetDomainById(locCharacteristic.DomainId);
                    int cboxIndex = cbox.Items.IndexOf(cbox.Value);
                    switch (locCharacteristic.DomainType)
                    {
                        case DomainType.Table:
                            // если характеристика - таблица, то сериализуем имя + RowID                            
                            string locRow = cbox.Value.ToString() + "|" + state[i];
                            _project.GetLIMitemByName(cName).Value = locRow;
                            break;
                        /*case domaintypes.CUBE:
                            // если характеристика - куб, то сериализуем ID куба + ID его фиксированных показателей                            
                            locLIM.GetLIMitemByName(sName).value = (grdSlots.Rows[i].Cells[2] as DataGridViewButtonCell).Tag;
                            break;*/
                        default:
                            // иначе значение комбобокса
                            _project.GetLIMitemByName(cName).Value = locDomain.GetItemByPosition(cboxIndex).Value;
                            break;
                    }
                }
                else
                {
                    cName = grdCharacteristics.Rows[i].Cells[0].Value.ToString();
                    _project.GetLIMitemByName(cName).Value = null;
                }
            }
        }

        /// <summary>
        /// Применяет настройки диалога и закрыает его
        /// </summary>
        private void ApplyAndClose()
        {
            string worldName = WorldsBox.Text;
            int worldKey = -1;
            try
            {
                worldKey = _project.Repository.GetOrSetWorldKeyByName(worldName);
            }
            catch (BIWorldEmptyNameException ex)
            {
                GeneralMethods.ShowUserError(ex.Message);
                WorldsBox.Focus();
                WorldsBox.SelectAll();
                DialogResult = DialogResult.None;
                return;
            }
            _project.LastWorldKey = worldKey;
            UpdateLIM();
            if (DebugLIM.Checked)
            {
                DialogResult = DialogResult.Yes;
                Close();
            }
        }

		private void OKButton_Click(object sender, EventArgs e)
		{
            ApplyAndClose();
		}

		private void grdCharacteristics_CurrentCellDirtyStateChanged(object sender, EventArgs e)
		{
			UpdateCurrentCell();
		}		

		private void grdRows_RowEnter(object sender, DataGridViewCellEventArgs e)
		{
            ProcessRowsGridChange(e.RowIndex);			
		}        

		private void grdCharacteristics_RowEnter(object sender, DataGridViewCellEventArgs e)
		{
            ProcessCharacteristicsGridChange(e.RowIndex);            
		}

        private void SaveButton_Click(object sender, EventArgs e)
        {
            SaveSettings();
        }    

        private void LogicalInferenceStartDialog_Load(object sender, EventArgs e)
        {
            Initialize();
        }

        public LogicalInferenceStartDialog(ProjectDescriptor currentProject)
        {
            _project = currentProject;
            InitializeComponent();
        }		

        private void CancelLISDButton_Click(object sender, EventArgs e)
        {
            Close();
        }

	}
}

